/*
 *  Copyright 2010-2011 Mark Eschbach
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 * $HeadURL$
 * $Id$
 */
package com.meschbach.psi.tomcat;

import com.meschbach.psi.ContainerFactory;
import com.meschbach.psi.PSIException;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Embedded;

/**
 *
 * @author "Mark Eschbach" &lt;meschbach@gmail.com&gt;
 */
public class LocalTomcatBuilder implements ContainerFactory {

    public TomcatContainer buildContainer() throws PSIException {
        /*
         * Tomcat 6 is a file based system...
         */
        File base;
        File targetBase = new File("target");
        if (!targetBase.exists()) {
            targetBase.mkdir();
        }
        base = new File(targetBase, "tomcat-working");
        if (!base.exists()) {
            base.mkdir();
        }
        /*
         * Build our mediating objecct
         */
        Embedded econtainer = new Embedded();
        econtainer.setCatalinaBase(base.getAbsolutePath());
        econtainer.setCatalinaHome(base.getAbsolutePath());
        /*
         * Create our engine
         */
        Engine e = econtainer.createEngine();
        /*
         * Create our host && configure the container
         */
        Host host = econtainer.createHost("localhost", base.getAbsolutePath());
        e.addChild(host);
        e.setDefaultHost(host.getName());
        /*
         * Activate the engine
         */
        econtainer.addEngine(e);
        /*
         * Create the connector
         */
        int port = findOpenPort();
        Connector c = econtainer.createConnector("localhost", port, false);
        econtainer.addConnector(c);
        /*
         * Start the contianer
         */
        try {
            econtainer.start();
        } catch (LifecycleException le) {
            throw new PSIException(le);
        }
        /*
         * Configure a Tomcat container for managing the container
         */
        return new TomcatContainer(base, "http://localhost:" + port, econtainer, host);
    }

    /**
     * The following method is ugly.  Horribly ugly.  But its a necessity
     * unfortunately due to Tomcat sprinkling copies of data everywhere.
     */
    public int findOpenPort() throws PSIException {
        ServerSocket s = null;
        try {
            s = new ServerSocket(0);
            return s.getLocalPort();
        } catch (IOException e) {
            throw new PSIException(e);
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (IOException ioe) {
                    throw new PSIException(ioe);
                }
            }
        }
    }
}
